home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
- This is free software distributed under the terms of the
- GNU Public License. See the file COPYING for details.
-
- $Id: util.c,v 1.98 2001/02/15 08:39:45 drscholl Exp $
-
- This file contains various utility functions useful elsewhere in this
- server */
-
- /* Modified 29/05/01 : init_random() modified to remove dependency on the
- for Amiga port : structure "global", which doesn't exist in Amiga GCC
- 2.7.0
- */
-
- #include <fcntl.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <ctype.h>
- #ifndef WIN32
- #include <unistd.h>
- #include <sys/time.h>
- #endif
- #include <stdlib.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
-
- #include "md5.h"
- #include "opennap.h"
- #include "debug.h"
-
- /* writes `val' as a two-byte value in little-endian format */
- void
- set_val (char *d, unsigned short val)
- {
- val = BSWAP16 (val);
- memcpy (d, &val, 2);
- }
-
- /* this is like strtok(2), except that all fields are returned as once. nul
- bytes are written into `pkt' and `template' is updated with pointers to
- each field in `pkt' */
- /* returns: number of fields found. */
- int
- split_line (char **template, int templatecount, char *pkt)
- {
- int i = 0;
-
- if (!pkt)
- return -1;
- while (ISSPACE (*pkt))
- pkt++;
- while (*pkt && i < templatecount)
- {
- if (*pkt == '"')
- {
- /* quoted string */
- pkt++;
- template[i++] = pkt;
- pkt = strchr (pkt, '"');
- if (!pkt)
- {
- /* bogus line */
- return -1;
- }
- *pkt++ = 0;
- if (!*pkt)
- break;
- pkt++; /* skip the space */
- }
- else
- {
- template[i++] = pkt;
- pkt = strpbrk (pkt, " \t\r\n");
- if (!pkt)
- break;
- *pkt++ = 0;
- }
- while (ISSPACE (*pkt))
- pkt++;
- }
- return i;
- }
-
- static char hex[] = "0123456789ABCDEF";
-
- void
- expand_hex (char *v, int vsize)
- {
- int i;
-
- for (i = vsize - 1; i >= 0; i--)
- {
- v[2 * i + 1] = hex[v[i] & 0xf];
- v[2 * i] = hex[(v[i] >> 4) & 0xf];
- }
- }
-
- void
- init_random (void)
- {
- /*ASSERT (global.current_time != 0);*/
- /* force generation of a different seed if respawning quickly by adding
- the pid of the current process */
- srand (/*global.current_time + */time(NULL) + getuid () + getpid ());
- }
-
- void
- get_random_bytes (char *d, int dsize)
- {
- int i = 0, v;
-
- while (i < dsize)
- {
- v = rand ();
- d[i++] = v & 0xff;
- if (i < dsize)
- d[i++] = (v >> 8) & 0xff;
- if (i < dsize)
- d[i++] = (v >> 16) & 0xff;
- if (i < dsize)
- d[i++] = (v >> 24) & 0xff;
- }
- }
-
- /* generate our own nonce value */
- char *
- generate_nonce (void)
- {
- char *nonce;
-
- nonce = MALLOC (17);
- if (!nonce)
- {
- OUTOFMEMORY ("generate_nonce");
- return 0;
- }
- nonce[16] = 0;
-
- get_random_bytes (nonce, 8);
-
- /* expand the binary data into hex for transport */
- expand_hex (nonce, 8);
-
- return nonce;
- }
-
- CHANNEL *
- new_channel (void)
- {
- CHANNEL *c = CALLOC (1, sizeof (CHANNEL));
-
- if (!c)
- {
- OUTOFMEMORY ("new_channel");
- return 0;
- }
- #ifdef DEBUG
- c->magic = MAGIC_CHANNEL;
- #endif
- return c;
- }
-
- char *
- strfcpy (char *dest, const char *src, size_t destlen)
- {
- strncpy (dest, src, destlen);
- dest[destlen - 1] = 0;
- return dest;
- }
-
- #if LOG_CHANNEL
- static int Logging = 0;
- #endif
-
- void
- log (const char *fmt, ...)
- {
- va_list ap;
-
- #if LOG_CHANNEL
- char buf[1024];
- int len;
- char *msg;
-
- strfcpy (buf + 4, "&LOG opennap ", sizeof (buf) - 4);
- len = strlen (buf + 4);
- msg = buf + len + 4;
- va_start (ap, fmt);
- vsnprintf (buf + 4 + len, sizeof (buf) - 4 - len, fmt, ap);
- va_end (ap);
-
- /* prevent infinite loop */
- if (!Logging)
- {
- len += strlen (buf + 4 + len);
- set_tag (buf, MSG_SERVER_PUBLIC);
- set_len (buf, len);
-
- Logging = 1;
- (void) send_to_channel ("&LOG", buf, len + 4);
- Logging = 0;
- }
-
- /* display log msg on console */
- fputs (msg, stdout);
- #else
- va_start (ap, fmt);
- vprintf (fmt, ap);
- va_end (ap);
- #endif
- fputc ('\n', stdout);
- fflush (stdout);
- }
-
- /* like next_arg(), except we don't skip over additional whitespace */
- char *
- next_arg_noskip (char **s)
- {
- char *r = *s;
-
- *s = strchr (r, ' ');
- if (*s)
- *(*s)++ = 0;
- return r;
- }
-
- char *
- next_arg (char **s)
- {
- char *r = *s;
-
- if (!r)
- return 0;
- while (ISSPACE (*r))
- r++;
- if (!*r)
- return 0;
- if (*r == '"')
- {
- r++;
- *s = strchr (r, '"');
- }
- else
- *s = strpbrk (r, " \t\r\n");
- if (*s)
- {
- *(*s)++ = 0;
- while (ISSPACE (**s))
- ++ * s;
- if (!**s)
- *s = 0; /* no more arguments */
- }
- return r;
- }
-
- char *
- strlower (char *s)
- {
- char *r = s;
-
- ASSERT (s != 0);
- while (*s)
- *s++ = tolower ((unsigned char) *s);
- return r;
- }
-
- int
- safe_realloc (void **ptr, int bytes)
- {
- void *t;
-
- t = REALLOC (*ptr, bytes);
- if (!t)
- return -1;
- *ptr = t;
- return 0;
- }
-
- void
- print_args (int ac, char **av)
- {
- int i;
-
- printf ("print_args(): [%d]", ac);
- for (i = 0; i < ac; i++)
- printf (" \"%s\"", av[i]);
- fputc ('\n', stdout);
- }
-
- static char alphabet[] =
-
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- #define alphabet(c) alphabet[(unsigned int)c]
-
- static int
- b64_encode (char *out, int *outsize, char *in, int insize)
- {
- unsigned char a, b, c, d;
- char *pout = out;
-
- while (insize > 0)
- {
- c = d = 0xff;
- a = (*in >> 2) & 0x3f;
- b = (*in & 0x3) << 4;
- in++;
- insize--;
- if (insize)
- {
- b |= (*in >> 4) & 0xf;
- c = (*in & 0xf) << 2;
- in++;
- insize--;
- if (insize)
- {
- c |= (*in >> 6) & 0x3;
- d = *in & 0x3f;
- in++;
- insize--;
- }
- }
- *out++ = alphabet (a);
- *out++ = alphabet (b);
- if (c != 0xff)
- {
- *out++ = alphabet (c);
- if (d != 0xff)
- *out++ = alphabet (d);
- else
- *out++ = '=';
- }
- else
- {
- *out++ = '=';
- *out++ = '=';
- }
- }
- *out = 0;
- *outsize = out - pout;
- return 0;
- }
-
- static char b64_lookup[128] = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
- -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
- };
-
- #define b64_lookup(c) b64_lookup[(unsigned int)c]
-
- static int
- b64_decode (char *out, int *outsize, const char *in)
- {
- unsigned char a, b, c, d;
- unsigned char b2, b3;
- char *pout = out;
-
- while (*in)
- {
- a = b64_lookup (*in++);
- b = b64_lookup (*in++);
- *out++ = a << 2 | b >> 4;
- b2 = b << 4;
- if (*in && *in != '=')
- {
- c = b64_lookup (*in++);
- b2 |= c >> 2;
- *out++ = b2;
- b3 = c << 6;
- if (*in && *in != '=')
- {
- d = b64_lookup (*in++);
- b3 |= d;
- *out++ = b3;
- }
- else
- break;
- }
- else
- break;
- }
- *outsize = out - pout;
- return 0;
- }
-
- int
- check_pass (const char *info, const char *pass)
- {
- struct md5_ctx md;
- char hash[16], real[16];
- int realsize;
-
- ASSERT (info != 0);
- ASSERT (pass != 0);
- if (*info != '1' || *(info + 1) != ',')
- return -1;
- info += 2;
- md5_init_ctx (&md);
- md5_process_bytes (info, 8, &md);
- info += 8;
- if (*info != ',')
- return -1;
- info++;
- md5_process_bytes (pass, strlen (pass), &md);
- md5_finish_ctx (&md, hash);
- realsize = sizeof (real);
- b64_decode (real, &realsize, info);
- ASSERT (realsize == 16);
- if (memcmp (real, hash, 16) == 0)
- return 0;
- return -1;
- }
-
- char *
- generate_pass (const char *pass)
- {
- struct md5_ctx md;
- char hash[16];
- char output[36]; /* 1,xxxxxxxx,xxxxxxxxxxxxxxxxxxxxxxx== */
- int outsize;
- int i;
-
- ASSERT (pass != 0);
- output[0] = '1';
- output[1] = ',';
- get_random_bytes (output + 2, 8);
- for (i = 0; i < 8; i++)
- output[i + 2] = alphabet[((unsigned int) output[i + 2]) % 64];
- output[10] = ',';
- md5_init_ctx (&md);
- md5_process_bytes (output + 2, 8, &md);
- md5_process_bytes (pass, strlen (pass), &md);
- md5_finish_ctx (&md, hash);
- outsize = sizeof (output) - 11;
- b64_encode (output + 11, &outsize, hash, 16);
- output[sizeof (output) - 3] = 0; /* strip the trailing == */
- return (STRDUP (output));
- }
-
- CHANNEL *
- find_channel (LIST * channels, const char *s)
- {
- for (; channels; channels = channels->next)
- if (!strcasecmp (((CHANNEL *) channels->data)->name, s))
- return channels->data;
- return 0;
- }
-
- void
- free_pointer (void *p)
- {
- FREE (p);
- }
-
- /* check to make sure this string is a valid host name. include the glob
- * characters
- */
- int
- invalid_host (const char *p)
- {
- while (*p)
- {
- if (!isalnum (*p) || !strchr (".-?*", *p))
- return 1;
- p++;
- }
- return 0;
- }
-